﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using CRONUS.BusinessObjects;
using CRONUS.Presentation;

namespace CRONUS
{
    public partial class CountryLimits : SecuredPageView<CountryLimitsPresenter, ICountryLimitsView>, ICountryLimitsView
    {
        #region Page methods
        protected void Page_Load(object sender, EventArgs e)
        {
            //work around for update panel watermark extender bug... 
            txtweComments.ID = DateTime.Now.ToString("ddMMyyyymmss");
            wucCountryLimitMaintenance1.CountryLimitHolderDeleted += new EventHandler<EventArgs>(wucCountryLimitMaintenance1_CountryLimitHolderDeleted);

            if (!IsPostBack)
            {
                BindGridsToClear();
                EnableControls(false);

                //select 1st tab
                countryLimitsTabControl_selectedTab.Value = "tab1";

                LimitsDate = ApplicationService.GetCurrentReportDate();
                IsRealTime = true;
                Presenter.LoadReportDates();

                //Get common data for drop downs
                Presenter.GetCountries();
                Presenter.GetRatingTypes();
                Presenter.GetOutlooks();

                //todo: out to func
                ListItem dummyOutlook = new ListItem("", "-1");
                ddlOutlook.Items.Add(dummyOutlook);
                ddlOutlook.SelectedIndex = ddlOutlook.Items.IndexOf(dummyOutlook);

                //Manually put the rating types into the ViewState as the control is also built manually
                ViewState["_ratingTypes"] = RatingTypes;
            }

            //Dynamic controls need to be added on every post back
            CreateRatingDropDowns();

            ManageComments();

            //Required for custom tab control
            System.Web.UI.ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "maintainTabState", "setTabState('countryLimitsTabControl');", true);
        }

        //add empty rows to stop most jumpy resizing
        protected void Page_PreRender(object sender, EventArgs e)
        {
            List<GridView> gridViews = new List<GridView>();
            gridViews.Add(grdCountryLimitHolders);
            gridViews.Add(grdBusinessUnitLimitHolders);
            gridViews.Add(grdRestrictions);
            gridViews.Add(grdBusinessUnitSubLimits);
            gridViews.Add(grdCountryComments);

            foreach (GridView gridView in gridViews)
            {
                if (gridView.Rows.Count > 0)
                {

                    for (int i = gridView.Rows.Count + 1; i <= gridView.PageSize; i++)
                    {
                        GridViewRow row = new GridViewRow(
                                0,
                                0,
                                DataControlRowType.DataRow,
                                (i % 2 > 0) ? DataControlRowState.Normal : DataControlRowState.Alternate);

                        foreach (DataControlField field in gridView.Columns)
                        {
                            TableCell cell = new TableCell();
                            cell.Text = "&nbsp;";//a space to force the row to the height of other rows
                            row.Cells.Add(cell);
                        }

                        gridView.Controls[0].Controls.AddAt(i, row);
                    }
                }
            }
        }

        /// <summary>
        /// Event registration can only be done in the Render method.
        /// So, need assign and register click events for rows here.
        /// </summary>
        protected override void Render(HtmlTextWriter writer)
        {
            List<GridView> gridsWithClickableRows = new List<GridView>();
            gridsWithClickableRows.Add(grdCountryLimitHolders);
            gridsWithClickableRows.Add(grdBusinessUnitLimitHolders);

            foreach (GridView gridView in gridsWithClickableRows)
            {
                //enable clickable rows
                foreach (GridViewRow row in gridView.Rows)
                {
                    if (row.RowType == DataControlRowType.DataRow)
                    {
                        bool addClickEvent = true;
                        if (selectedRows.ContainsKey(gridView))
                        {
                            if ((int)gridView.DataKeys[row.RowIndex].Value == selectedRows[gridView])
                            {
                                addClickEvent = false;
                            }
                        }

                        if (addClickEvent)
                        {
                            row.Attributes.Add("onclick", Page.ClientScript.GetPostBackEventReference(gridView, "Select$" + gridView.DataKeys[row.RowIndex].Value.ToString(), true));
                            row.Attributes.Add("onmouseover", "this.style.backgroundColor = 'lightgrey'");//mouse over light grey
                            row.Attributes.Add("onmouseout", "this.style.backgroundColor = '" + row.Style["backgroundColor"] + "'");//mouse out back to original colour
                        }
                        row.Style.Add("cursor", "hand");
                    }
                }
            }
            base.Render(writer);
        }

        #endregion

        #region Public methods
        /// <summary>
        /// Used to support showing the wucBusinessUnitLimitMaintenance1 modal 
        /// dialog from other modals shown by this page
        /// </summary>
        /// <param name="businessUnitLimitHolder"></param>
        /// <param name="limitHolders"></param>
        public void ShowBusinessUnitLimitMaintenanceModal(LimitHolderBusinessUnit businessUnitLimitHolder,
            IEnumerable<LimitHolderBusinessUnit> limitHolders)
        {
            wucBusinessUnitLimitMaintenance1.Show(CountryDetails, businessUnitLimitHolder, limitHolders, btnAddBusinessUnitSubLimit.Visible, true, IsRealTime);
        }

        public void ShowNewBusinessUnitLimitMaintenanceModal(CountryLimitHolder climitHolder)
        {
            wucBusinessUnitLimitMaintenance1.ShowNew(CountryDetails, climitHolder, true);
        }

        //Used to support showing the wucBusinessUnitSubLimitMaintenance1 modal
        //dialog from other modals shown by this page
        public void ShowBusinessUnitSubLimitMaintenanceModal(LimitHolderBusinessUnit businessUnitLimitHolder, BusinessUnitSubLimit businessUnitSubLimit)
        {
            wucBusinessUnitSubLimitMaintenance1.Show(businessUnitLimitHolder, businessUnitSubLimit, true, IsRealTime);
        }

        public void ShowNewBusinessUnitSubLimitMaintenanceModal(LimitHolderBusinessUnit businessUnitLimitHolder)
        {
            wucBusinessUnitSubLimitMaintenance1.ShowNew(businessUnitLimitHolder, true);
        }

        /// <summary>
        /// For calling from child modal dialogs when this parent page needs updating as 
        /// a result of changes in the dialog
        /// </summary>
        public void Update()
        {
            PopulateCountryData();
        }

        /// <summary>
        /// Update main screen and select new business unit in grid
        /// </summary>
        /// <param name="lhbu"></param>
        public void Update(LimitHolderBusinessUnit lhbu)
        {
            this.SelectLimitHolderBusinessUnit(lhbu.Id, lhbu.ParentSourceSystem.Id);
            this.Update();
        }

        /// <summary>
        /// Update main screen and select new limit holder
        /// </summary>
        /// <param name="lhbu"></param>
        public void Update(CountryLimitHolder lh)
        {
            this.Update();
            this.SelectLimitHolder(lh.Id, lh.LimitHolder.Description);
        }

        /// <summary>
        /// Show a modal popup alert dialogue
        /// </summary>
        /// <param name="caption">Top level caption</param>
        /// <param name="info">Infromation text</param>
        public void ShowAlert(string caption, string info)
        {
            lblCaption.Text = caption;
            lblText.Text = info;
            mpeAlert.Show();
        }

        /// <summary>
        /// For calling from child modal dialogs when the selected business unit 
        /// needs setting 
        /// </summary>
        public void SetLimitHolderBusinessUnit(int Id, string sourceSystem)
        {
            this.SelectLimitHolderBusinessUnit(Id, sourceSystem);
        }

        #endregion Public methods

        #region Private methods

        private void ManageComments()
        {
            //Disable the watermark extender if unsaved comments are present.
            if (txtCommentsRequired.Text != string.Empty && txtCommentsRequired.Text != "Enter Comments")
            {
                txtweComments.Enabled = false;
                txtComments.Text += txtCommentsRequired.Text;
                txtComments.Text += "\r\n";
                txtCommentsRequired.Text = string.Empty;
                ddlSelectCountry.Enabled = false;
                lnkViewHistoricDates.Enabled = false;
                string saveCommentsMessage = "This control will be enabled when the comments have been saved";
                ddlSelectCountry.ToolTip = saveCommentsMessage;
                lnkViewHistoricDates.ToolTip = saveCommentsMessage;
            }
            else
            {
                txtweComments.Enabled = true;
                ddlSelectCountry.Enabled = true;
                lnkViewHistoricDates.Enabled = true;
                ddlSelectCountry.ToolTip = string.Empty;
                lnkViewHistoricDates.ToolTip = string.Empty;
            }
        }

        /// <summary>
        /// Enable or disable edit controls 
        /// </summary>
        /// <param name="bEnable"></param>
        private void EnableControls(bool bEnable)
        {
            btnAddRestrictionComment.Visible = bEnable;

            btnAddBusinessUnitSubLimit.Visible = bEnable;
            btnNewBusinessUnitLimitHolder.Visible = bEnable;

            txtComments.Enabled = bEnable;
            CronusHelper.SetReadOnlyTextBox(txtComments, !bEnable);

            btnSave.Visible = bEnable;
            ddlOutlook.Enabled = bEnable;

            CronusHelper.SetReadOnlyTextBox(txtGDP, !bEnable);

            if (RatingTypes != null)
            {
                foreach (RatingType ratingType in RatingTypes)
                {
                    DropDownList ddl = (DropDownList)RatingsPlaceHolder.FindControl("ratingType_" + ratingType.Id.ToString());
                    ddl.Enabled = bEnable;
                }
            }
        }

        /// <summary>
        /// Enable or disable 'comments' controls 
        /// </summary>
        /// <param name="bEnable"></param>
        private void EnableComment(bool bEnable)
        {
            txtComments.Enabled = bEnable;
            CronusHelper.SetReadOnlyTextBox(txtComments, !bEnable);

            btnSave.Visible = bEnable;
        }

        private void BindGridsToClear()
        {
            //Bind to nothing to get 'no data' message from grid
            grdCountryLimitHolders.DataBind();
            grdBusinessUnitLimitHolders.DataBind();
            grdBusinessUnitSubLimits.DataBind();
            grdRestrictions.DataBind();
            grdCountryComments.DataBind();
        }

        private void CreateRatingDropDowns()
        {
            if (RatingTypes == null)
            {
                RatingTypes = (IEnumerable<RatingType>)ViewState["_ratingTypes"];
            }

            if (RatingTypes != null)
            {
                StringBuilder s_ratings = new StringBuilder();

                foreach (RatingType ratingType in RatingTypes)
                {
                    DropDownList ddl = new DropDownList();
                    ddl.ID = "ratingType_" + ratingType.Id.ToString();
                    ddl.Width = 440;
                    ddl.CssClass = "ratingSelect";
                    Label label = new Label();
                    label.Text = ratingType.DisplayName;

                    ddl.DataSource = ratingType.Ratings;
                    ddl.DataTextField = "Description";
                    ddl.DataValueField = "Id";
                    ddl.DataBind();
                    ddl.Enabled = false;// create them disabled and enable later

                    //Add and select dummy blank element (will be removed when country selected)
                    ListItem dummy = new ListItem("", "-1");
                    ddl.Items.Add(dummy);
                    ddl.SelectedIndex = ddl.Items.IndexOf(dummy);

                    RatingsPlaceHolder.Controls.Add(label);
                    RatingsPlaceHolder.Controls.Add(ddl);
                }
            }
        }

        private void PopulateCountryData()
        {
            if (ddlSelectCountry.SelectedIndex > 0)
            {
                //Remove dummy elements
                foreach (RatingType ratingType in RatingTypes)
                {
                    DropDownList ddl = (DropDownList)RatingsPlaceHolder.FindControl("ratingType_" + ratingType.Id.ToString());
                    ddl.Items.Remove(new ListItem("", "-1"));
                }

                ddlOutlook.Items.Remove(new ListItem("", "-1"));

                Presenter.GetOutlooks();//todo: why isn't this saved in viewstate as bound to asp ddl??
                Presenter.GetCountry(ddlSelectCountry.SelectedValue, LimitsDate);
                Presenter.GetCountryLimitHolders(CountryDetails, LimitsDate);

                if (CountryLimitHolders.Count() > 0)
                {
                    Presenter.Sort(grdCountryLimitHolders.ID);

                    //Select the first row of the CountryLimitHolder data grid by default
                    int defaultLimitHolderRowId = int.Parse(grdCountryLimitHolders.DataKeys[grdCountryLimitHolders.Rows[0].RowIndex].Value.ToString());

                    if (selectedLimitHolder.Value == "-1") //don't reset to the default on update
                    {
                        this.SelectLimitHolder(defaultLimitHolderRowId);
                    }
                    else
                        DisplaySelectedLimitHolder();

                    Presenter.GetBusinessUnitLimitHolders(CountryDetails, int.Parse(selectedLimitHolder.Value));

                    //Select the first row of the BusinessUnitLimitHolder data grid by default
                    if (grdBusinessUnitLimitHolders.Rows.Count > 0)
                    {
                        Presenter.Sort(grdBusinessUnitLimitHolders.ID);
                        LimitHolderBusinessUnit lhbu;

                        if (selectedBusinessUnit.Value == "-1")
                        {
                            lhbu = this.BusinessUnitLimitHolders.ElementAt(grdBusinessUnitLimitHolders.Rows[0].RowIndex);
                            this.SelectLimitHolderBusinessUnit(lhbu.Id, lhbu.ParentSourceSystem.Name);
                        }
                        else
                        {
                            lhbu = this.BusinessUnitLimitHolders.Where(l => l.Id == int.Parse(selectedBusinessUnit.Value)).First();
                            DisplaySelectedLimitHolderBusinessUnit();
                        }

                        Presenter.GetBusinessUnitSubLimits(lhbu);

                        // Get all bsiness unit sub limits for the currently selected limit holder business unit in order
                        // to determine if we can add child sub limits 
                        // Presenter.GetAllBusinessUnitSubLimits(lhbu.ParentSourceSystem.Id);

                    }
                    else
                    {
                        //No data to show
                        this.SelectLimitHolderBusinessUnit(-1, string.Empty);

                        grdBusinessUnitLimitHolders.DataBind();
                        grdBusinessUnitSubLimits.DataBind();
                    }
                }
                else
                {
                    //If there are no parents clear out the children.
                    this.SelectLimitHolderBusinessUnit(-1, string.Empty);
                    btnNewBusinessUnitLimitHolder.Visible = false;
                    grdBusinessUnitLimitHolders.DataBind();
                    grdBusinessUnitSubLimits.DataBind();
                }

                //Set default sort direction for grids dislaying data in date order
                setSortDirection("grdRestrictions", SortDirection.Descending);
                setSortDirection("grdCountryComments", SortDirection.Descending);

                // Enable or disable controls based on current permissions
                Presenter.SetPermissions(LimitsDate, selectedBusinessUnitName.Value);
            }
        }

        private void SetSelectedRowStyle(GridView gridView, int rowId)
        {
            selectedRows.Remove(gridView);

            foreach (GridViewRow row in gridView.Rows)
                foreach (TableCell tc in row.Cells)
                    tc.Font.Bold = false;

            foreach (GridViewRow row in gridView.Rows)
            {
                if ((int)gridView.DataKeys[row.RowIndex].Value == rowId)
                {
                    foreach (TableCell tc in row.Cells)
                        tc.Font.Bold = true;
                    selectedRows.Add(gridView, rowId);
                    break;
                }
            }
        }

        /// <summary>
        /// Select a business unit limit holder on ther grid
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="sourceSystem"></param>
        private void SelectLimitHolderBusinessUnit(int Id, string sourceSystem)
        {
            selectedBusinessUnit.Value = Id.ToString();
            selectedBusinessUnitName.Value = sourceSystem;

            SetSelectedRowStyle(grdBusinessUnitLimitHolders, Id);
        }

        /// <summary>
        /// Select a business unit limit holder on ther grid
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="sourceSystem"></param>
        private void SelectLimitHolder(int Id, string code)
        {
            selectedLimitHolder.Value = Id.ToString();
            selectedLimitHolderName.Value = code;

            SetSelectedRowStyle(grdCountryLimitHolders, Id);
        }

        private void SelectLimitHolder(int Id)
        {
            string desc = (from l in CountryLimitHolders
                           where l.Id == Id
                           select l.LimitHolder).Single().Description;
            SelectLimitHolder(Id, desc);
        }

        private void DisplaySelectedLimitHolder()
        {
            int id = int.Parse(selectedLimitHolder.Value);
            SetSelectedRowStyle(grdCountryLimitHolders, id);
        }

        private void DisplaySelectedLimitHolderBusinessUnit()
        {
            int id = int.Parse(selectedBusinessUnit.Value);
            SetSelectedRowStyle(grdBusinessUnitLimitHolders, id);
        }
        #endregion Private methods

        #region ICountryLimitsView

        public IEnumerable<CountryLimitHolder> CountryLimitHolders
        {
            get
            {
                return this.CountryDetails.LimitHolders;
            }
            set
            {
                this.CountryDetails.LimitHolders = value.ToList();
                grdCountryLimitHolders.DataSource = value;
                grdCountryLimitHolders.DataBind();
            }
        }

        public IEnumerable<LimitHolderBusinessUnit> BusinessUnitLimitHolders
        {
            get
            {
                return (IEnumerable<LimitHolderBusinessUnit>)ViewState["_businessUnitLimitHolders"];
            }
            set
            {
                ViewState["_businessUnitLimitHolders"] = value;
                grdBusinessUnitLimitHolders.DataSource = value;
                grdBusinessUnitLimitHolders.DataBind();
            }
        }

        public IEnumerable<RatingType> RatingTypes { get; set; }

        public IEnumerable<Country> Countries
        {
            get
            {
                return (IEnumerable<Country>)ddlSelectCountry.DataSource;
            }
            set
            {
                ddlSelectCountry.DataSource = value;
                ddlSelectCountry.DataTextField = "Name";
                ddlSelectCountry.DataValueField = "Code";
                ddlSelectCountry.DataBind();
            }
        }

        public Country CountryDetails
        {
            get
            {
                return (Country)ViewState["_country"];
            }
            set
            {
                ViewState["_country"] = value;

                txtIso2Code.Text = value.Code;
                txtBoeCode.Text = value.BankOfEnglandCode;
                txtCountryLimit.Text = value.Limit.ToString("#,##0");
                txtRiskWeight.Text = value.RiskWeight.ToString("#,##0");
                txtGDP.Text = value.GDPNominal.ToString("#,##0");
                ddlOutlook.SelectedIndex = Outlooks.Keys.ToList().IndexOf(value.Outlook.ToString());

                foreach (RatingType ratingType in RatingTypes)
                {
                    DropDownList ddl = (DropDownList)RatingsPlaceHolder.FindControl("ratingType_" + ratingType.Id.ToString());
                    ddl.Enabled = true;
                    ddl.SelectedIndex = ddl.Items.Count - 1; //default selection as 'No Rating'

                    foreach (Rating rating in value.Ratings)
                    {
                        if (rating.RatingType.Id == ratingType.Id)
                        {
                            ddl.SelectedIndex = ddl.Items.IndexOf(new ListItem(rating.Description, rating.Id.ToString()));
                        }
                    }
                }
            }
        }

        public IDictionary<string, int> Outlooks
        {
            get { return (IDictionary<string, int>)ddlOutlook.DataSource; }
            set
            {
                ddlOutlook.DataSource = value;
                ddlOutlook.DataTextField = "Key";
                ddlOutlook.DataValueField = "Value";
                ddlOutlook.DataBind();
            }
        }

        public IEnumerable<CountryRestriction> Restrictions
        {
            get
            {
                return (IEnumerable<CountryRestriction>)grdRestrictions.DataSource;
            }
            set
            {
                grdRestrictions.DataSource = value;
                grdRestrictions.DataBind();
            }
        }

        public IEnumerable<CountryComment> CountryComments
        {
            get
            {
                return (IEnumerable<CountryComment>)grdCountryComments.DataSource;
            }
            set
            {
                grdCountryComments.DataSource = value;
                grdCountryComments.DataBind();
            }
        }

        public IEnumerable<BusinessUnitSubLimit> BusinessUnitSubLimits
        {
            get
            {
                return (IEnumerable<BusinessUnitSubLimit>)ViewState["_businessUnitSubLimits"];
            }
            set
            {
                ViewState["_businessUnitSubLimits"] = value;
                grdBusinessUnitSubLimits.DataSource = value;
                grdBusinessUnitSubLimits.DataBind();
            }
        }

        /// <summary>
        /// Dettermine if the currently selected b has child bus and if so display the add sub limit button
        /// TO DO Place in viewstate to save a database call later when displaying the sub limit form.
        /// </summary>
        public IEnumerable<SourceSystem> AvailableBusinessUnitSubLimits
        {

            get
            {
                return null; //(IEnumerable<SourceSystem>)ViewState["_AbusinessUnitSubLimits"];
            }

            set
            {
                //ViewState["_AbusinessUnitSubLimits"] = value;
                // Cannot add child business units if no children exist
                //btnAddBusinessUnitSubLimit.Visible = value.Count() > 0;
            }
        }

        public IEnumerable<DateTime> AvailableLimitsDates
        {
            set
            {
                lvLimitsDates.DataSource = value;
                lvLimitsDates.DataBind();
            }
        }

        public DateTime LimitsDate
        {
            get { return ApplicationService.CronusSession.LimitsDate; }
            set
            {
                lblCurrentLimitsDate.Text = "Currently viewing limits data for " + value.ToShortDateString();
                ApplicationService.CronusSession.LimitsDate = value;
            }
        }

        public bool IsRealTime
        {
            get { return (bool)ViewState["_isRealTime"]; }
            set { ViewState["_isRealTime"] = value; }
        }

        public bool CanEdit
        {
            set { EnableControls(value); }
        }

        public bool CanComment
        {
            set { EnableComment(value); }
        }

        public bool CanAddNewCountryLimitHolder
        {
            set { btnNewCountryLimitHolder.Visible = value; }
        }

        public bool SubLimitCRUDEnabled
        {
            get { return (bool)ViewState["_subLimitVRUDEnabled"]; }
            set
            {
                ViewState["_subLimitVRUDEnabled"] = value;
                btnAddBusinessUnitSubLimit.Visible = value;
            }
        }

        #endregion

        #region Event Handlers

        protected void lnkViewHistoricDates_Click(object sender, EventArgs e)
        {
            mpeHistoricDates.Show();
        }

        protected void btnCancelHistoricDate_click(object sender, EventArgs e)
        {
            mpeHistoricDates.Hide();
        }

        //Event from ListView
        protected void OnSelectedLimitsDate(object sender, CommandEventArgs args)
        {
            LimitsDate = DateTime.Parse(args.CommandArgument.ToString());

            if (LimitsDate == ApplicationService.GetCurrentReportDate())
            {
                IsRealTime = true;
            }
            else
            {
                IsRealTime = false;
            }

            this.SelectLimitHolder(-1, string.Empty);
            this.SelectLimitHolderBusinessUnit(-1, string.Empty);
            PopulateCountryData();

            mpeHistoricDates.Hide();
        }


        void wucCountryLimitMaintenance1_CountryLimitHolderDeleted(object sender, EventArgs e)
        {
            this.SelectLimitHolder(-1, string.Empty);
        }


        protected void ddlSelectCountry_SelectedIndexChanged(object sender, EventArgs e)
        {
            //LimitsDate = DateTime.Parse(ddlReportDate.SelectedValue);
            this.SelectLimitHolder(-1, string.Empty);
            this.SelectLimitHolderBusinessUnit(-1, string.Empty);
            PopulateCountryData();
        }

        /// <summary>
        /// Both grdCountryLimitHolders and grdBusinessUnitLimitHolders support clickable rows.
        /// When a row is clicked the row's child data grid is rebound.
        /// </summary>
        protected void OnRowClicked(object sender, GridViewRowClickedEventArgs args)
        {
            if (((GridView)sender).ID == "grdCountryLimitHolders")
            {
                int lhId = (int)args.RowID;

                Presenter.GetBusinessUnitLimitHolders(CountryDetails, lhId);

                //Presenter.GetCountryLimitHolders(CountryDetails, LimitsDate);
                //Presenter.GetBusinessUnitLimitHolders(CountryDetails, lhId);

                Presenter.Sort(grdCountryLimitHolders.ID);

                var lh = CountryLimitHolders.Where(l => l.Id == lhId).Single();

                this.SelectLimitHolder((int)args.RowID, lh.LimitHolder.Description);

                if (grdBusinessUnitLimitHolders.Rows.Count > 0)
                {
                    var lhbu = lh.BusinessUnits.FirstOrDefault();
                    if (lhbu != null)
                    {
                        Presenter.GetBusinessUnitSubLimits(lhbu);
                        this.SelectLimitHolderBusinessUnit(lhbu.Id, lhbu.ParentSourceSystem.Name);
                    }
                    else
                    {
                        this.SelectLimitHolderBusinessUnit(-1, string.Empty);
                    }
                    // Display the add  sub limit unit button when not read only , gr admin role and parent bu has child bus
                    //if ((this.IsCurrentReportDate && CRONUSSession.ApplicationRole == RoleType.GRAdmin))
                    //    Presenter.GetAllBusinessUnitSubLimits(lhbu.ParentSourceSystem.Id);
                }
                else
                {
                    this.SelectLimitHolderBusinessUnit(-1, string.Empty);

                    //grdBusinessUnitLimitHolders.DataBind();
                    grdBusinessUnitSubLimits.DataBind();
                }
            }
            else if (((GridView)sender).ID == "grdBusinessUnitLimitHolders")
            {

                var lhbu = BusinessUnitLimitHolders.Where(b => b.Id == (int)args.RowID).First();

                // Display the add  sub limit unit button when not read only , gr admin role and parent bu has child bus
                //if( this.IsCurrentReportDate && CRONUSSession.ApplicationRole == RoleType.GRAdmin)
                //    Presenter.GetAllBusinessUnitSubLimits(lhbu.ParentSourceSystem.Id);

                selectedRows.Remove(grdBusinessUnitLimitHolders);

                Presenter.GetBusinessUnitSubLimits(lhbu);

                this.SelectLimitHolderBusinessUnit(lhbu.Id, lhbu.ParentSourceSystem.Name);

                Presenter.SetPermissions(LimitsDate, selectedBusinessUnitName.Value);
            }
        }

        protected void OnEditCountryLimitHolder(object sender, CommandEventArgs e)
        {
            int id = int.Parse(e.CommandArgument.ToString());
            // TO DO Move to presentation layer
            int cid = 0;
            int.TryParse(this.selectedLimitHolder.Value, out cid);

            if (id != cid)
            {
                this.SelectLimitHolder(id);
                this.Presenter.GetBusinessUnitLimitHolders(CountryDetails, id);
                this.SelectLimitHolderBusinessUnit(-1, string.Empty);

                grdBusinessUnitSubLimits.DataBind();
            }
            wucCountryLimitMaintenance1.Show(CountryDetails, id, LimitsDate);
        }

        protected void OnEditBusinessUnitLimitHolder(object sender, CommandEventArgs e)
        {
            // TO DO the presentation needs to be revisited, too much code in this form
            // and cascading display needs to be handled by presentation layer.
            int id = int.Parse(e.CommandArgument.ToString());
            LimitHolderBusinessUnit lhbu = BusinessUnitLimitHolders.Where(b => b.Id == id).SingleOrDefault();
            SelectLimitHolderBusinessUnit(id, lhbu.ParentSourceSystem.Name);
            Presenter.GetBusinessUnitSubLimits(lhbu);
            //Presenter.GetAllBusinessUnitSubLimits(lhbu.ParentSourceSystem.Id);
            wucBusinessUnitLimitMaintenance1.Show(CountryDetails, lhbu, BusinessUnitLimitHolders, btnAddBusinessUnitSubLimit.Visible, false, IsRealTime);
        }

        protected void OnEditBusinessUnitSubLimit(object sender, CommandEventArgs e)
        {
            // Get sub business unit id
            int sbuId = int.Parse(e.CommandArgument.ToString());
            int slhbuId = int.Parse(selectedBusinessUnit.Value);
            var lhbu = BusinessUnitLimitHolders.Where(b => b.Id == slhbuId).Single();
            var slbu = lhbu.SubLimits.Where(s => s.Id == sbuId).Single();
            wucBusinessUnitSubLimitMaintenance1.Show(lhbu, slbu, false, IsRealTime);
        }

        protected void btnAddBusinessUnitSubLimit_Click(object sender, EventArgs e)
        {
            //Not sure how usable this is.
            wucBusinessUnitSubLimitMaintenance1.ShowNew(
                BusinessUnitLimitHolders.Where(b => b.Id == int.Parse(selectedBusinessUnit.Value)).Single(),
                false);
        }

        protected void EditRestrictionComment(object sender, CommandEventArgs e)
        {
            wucRestrictionsComment1.Show(CountryDetails, int.Parse(e.CommandArgument.ToString()));
        }

        protected void AddRestrictionComment(object sender, EventArgs e)
        {
            wucRestrictionsComment1.ShowNew(CountryDetails);
        }

        protected void btnNewCountryLimitHolder_Click(object sender, EventArgs e)
        {
            //show CountryLimitMaintenance modal
            wucCountryLimitMaintenance1.ShowNew(CountryDetails, LimitsDate);
        }

        protected void btnAddNewBusinessUnitLimitHolder_Click(object sender, EventArgs e)
        {
            wucBusinessUnitLimitMaintenance1
                .ShowNew(CountryDetails
                , CountryLimitHolders.Where(l => l.Id == int.Parse(selectedLimitHolder.Value)).Single()
                , false);
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {
            bool updateCountry = false;
            bool updateRatings = false;

            //Only add comment if there is one
            if (txtComments.Text != string.Empty)
            {
                Presenter.AddCountryComment(CountryDetails, txtComments.Text, User.UserName, LimitsDate);
                txtComments.Text = string.Empty;
            }

            //Check for updates to Outlook & GDPNominal
            if (CountryDetails.Outlook != (Outlook)int.Parse(ddlOutlook.SelectedItem.Value))
            {
                CountryDetails.Outlook = (Outlook)int.Parse(ddlOutlook.SelectedItem.Value);
                updateCountry = true;
            }
            if (CountryDetails.GDPNominal != long.Parse(txtGDP.Text.Replace(",", "")))
            {
                CountryDetails.GDPNominal = long.Parse(txtGDP.Text.Replace(",", ""));
                updateCountry = true;
            }

            //Update ratings from the UI
            foreach (RatingType ratingType in RatingTypes)
            {
                DropDownList ddl = (DropDownList)RatingsPlaceHolder.FindControl("ratingType_" + ratingType.Id.ToString());

                //todo: need deep compare
                var matchedRatings = from rat in CountryDetails.Ratings
                                     where rat.Id == int.Parse(ddl.SelectedValue)
                                     && rat.Description == ddl.SelectedItem.Text
                                     && "ratingType_" + rat.RatingType.Id.ToString() == ddl.ID
                                     && rat.RatingType.Description == ratingType.Description
                                     select rat;

                //If there has been a change to this rating make the update in CountryDetails
                if (matchedRatings.Count() == 0)
                {
                    //Remove rating for this type and add the new one
                    CountryDetails.Ratings.Remove(CountryDetails.Ratings.Where(r => r.RatingType.Id == ratingType.Id && r.RatingType.Description == ratingType.Description).SingleOrDefault());
                    CountryDetails.Ratings.Add(new Rating(ratingType) { Id = int.Parse(ddl.SelectedValue) });
                    updateRatings = true;
                }
            }

            //Only update the country if there are changes to the Outlook or GDP
            if (updateCountry)
            {
                Presenter.UpdateCountry(CountryDetails, User.UserName);
            }

            //Only update the ratings if they've changed
            if (updateRatings)
            {
                Presenter.UpdateCountryRatings(CountryDetails, User.UserName, LimitsDate);
            }
        }

        #endregion

        #region grid view support

        private Dictionary<GridView, int> selectedRows = new Dictionary<GridView, int>();

        protected void OnRowCreated(Object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == DataControlRowType.Header)
            {
                GridView gv = (GridView)sender;
                int sortColumnIndex = GetSortColumnIndex(gv);
                if (sortColumnIndex != -1)
                {
                    AddSortImage(sortColumnIndex, e.Row, gv.ID);
                }
            }
        }

        protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
        {
            if (string.IsNullOrEmpty(eventArgument) == false && eventArgument.StartsWith("Select"))
            {
                int id = Int32.Parse(eventArgument.Substring(7));
                GridViewRowClickedEventArgs args = new GridViewRowClickedEventArgs(id);
                OnRowClicked(sourceControl, args);
            }
            else
            {
                base.RaisePostBackEvent(sourceControl, eventArgument);
            }
        }


        public class GridViewRowClickedEventArgs : EventArgs
        {
            private object _rowID;

            public GridViewRowClickedEventArgs(object rowID)
            {
                _rowID = rowID;
            }
            public object RowID
            {
                get { return _rowID; }
            }
        }

        protected void OnSorting(object sender, GridViewSortEventArgs e)
        {
            GridView gv = (GridView)sender;
            string scol = this.getSortExpression(gv.ID);
            SortDirection cdir = this.getSortDirection(gv.ID);
            // Expression not changed
            if (scol != e.SortExpression)
                setSortExpression(gv.ID, e.SortExpression);
            else
            {
                if (cdir == SortDirection.Descending)
                    cdir = SortDirection.Ascending;
                else
                    cdir = SortDirection.Descending;
                this.setSortDirection(gv.ID, cdir);
            }

            switch (gv.ID)
            {
                case "grdCountryLimitHolders":
                    Presenter.GetCountryLimitHolders(CountryDetails, LimitsDate);
                    break;
                case "grdBusinessUnitLimitHolders":
                    Presenter.GetBusinessUnitLimitHolders(CountryDetails, int.Parse(selectedLimitHolder.Value));
                    break;
                case "grdRestrictions":
                    Presenter.GetRestrictions(ddlSelectCountry.SelectedValue, LimitsDate);
                    break;
                case "grdBusinessUnitSubLimits":
                    this.BusinessUnitLimitHolders = this.BusinessUnitLimitHolders;
                    break;
                case "grdCountryComments":
                    Presenter.GetCountryComments(ddlSelectCountry.SelectedValue, LimitsDate);
                    break;
            }
            this.Presenter.Sort(gv.ID);
        }

        private void AddSortImage(int columnIndex, GridViewRow headerRow, string Id)
        {
            var sortImage = new System.Web.UI.WebControls.Image();
            if (this.getSortDirection(Id) == SortDirection.Ascending)
            {
                sortImage.ImageUrl = "Content/Images/arrowUp.png";
                sortImage.AlternateText = "Ascending Order";
            }
            else
            {
                sortImage.ImageUrl = "Content/Images/arrowDown.png";
                sortImage.AlternateText = "Descending Order";
            }
            headerRow.Cells[columnIndex].Controls.Add(sortImage);
        }

        /// <summary>
        /// Gridview sort direction
        /// </summary>
        private SortDirection getSortDirection(string grid)
        {
            SortDirection? dir = Session[string.Format("{0}_SortDirection", grid)] as SortDirection?;
            return dir ?? SortDirection.Ascending;
        }

        private void setSortDirection(string grid, SortDirection value)
        {
            Session[string.Format("{0}_SortDirection", grid)] = value;
        }

        /// <summary>
        /// Gridview sort expression
        /// </summary>
        private string getSortExpression(string grid)
        {

            string sexp = (string)Session[string.Format("{0}_SortExpression", grid)];
            if (sexp == null)
            {
                if (grid == grdCountryLimitHolders.ID)
                    sexp = "LimitHolder";
                else if (grid == grdBusinessUnitLimitHolders.ID || grid == grdBusinessUnitSubLimits.ID)
                    sexp = "Id";
                else if (grid == grdRestrictions.ID)
                    sexp = "UpdatedDate";
                else if (grid == grdCountryComments.ID)
                    sexp = "UpdatedDate";
            }
            return sexp;
        }

        private void setSortExpression(string grid, string value)
        {
            Session[string.Format("{0}_SortExpression", grid)] = value;
        }

        private int GetSortColumnIndex(GridView gv)
        {
            string scol = this.getSortExpression(gv.ID);
            foreach (DataControlField field in gv.Columns)
            {
                if (field.SortExpression == scol)
                    return gv.Columns.IndexOf(field);
            }
            return -1;
        }

        protected void OnPageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            GridView gv = (GridView)sender;
            if (e.NewPageIndex > -1)
            {
                gv.PageIndex = e.NewPageIndex;
                this.setPageIndex(gv.ID, e.NewPageIndex);

                switch (gv.ID)
                {
                    case "grdCountryLimitHolders":
                        Presenter.GetCountryLimitHolders(CountryDetails, LimitsDate);
                        break;
                    case "grdBusinessUnitLimitHolders":
                        Presenter.GetBusinessUnitLimitHolders(CountryDetails, int.Parse(selectedLimitHolder.Value));
                        break;
                    case "grdRestrictions":
                        Presenter.GetRestrictions(ddlSelectCountry.SelectedValue, LimitsDate);
                        break;
                    case "grdBusinessUnitSubLimits":
                        this.BusinessUnitLimitHolders = this.BusinessUnitLimitHolders;
                        //Presenter.GetBusinessUnitSubLimits(int.Parse(selectedBusinessUnit.Value));
                        break;
                    case "grdCountryComments":
                        Presenter.GetCountryComments(ddlSelectCountry.SelectedValue, LimitsDate);
                        break;
                }

                this.Presenter.Sort(gv.ID);
            }
        }

        private void setPageIndex(string grid, int value)
        {
            Session[string.Format("{0}_PageIndex", grid)] = value;
        }

        public string GetSortDirection(string ID)
        {
            SortDirection dir = getSortDirection(ID);
            string sdir;
            if (dir == SortDirection.Ascending)
                sdir = "ASC";
            else
                sdir = "DESC";
            return sdir;
        }

        public string GetSortExpression(string ID)
        {
            return getSortExpression(ID);
        }

        #endregion
    }
}
